package service

import (
	"context"
	"gin_im/define"
	"gin_im/helper"            // 导入辅助工具包
	"gin_im/models"            // 导入数据模型包
	"github.com/gin-gonic/gin" // 导入Gin框架包
	"log"
	"net/http" // 导入HTTP包
	"time"
)

// Login 用户登录处理函数
func Login(c *gin.Context) {
	account := c.PostForm("account")   // 从表单获取账号
	password := c.PostForm("password") // 从表单获取密码

	//println(account, password, helper.GetMd5(password)) // 调试打印（注释状态）

	// 参数验证：检查账号或密码是否为空
	if account == "" || password == "" {
		c.JSON(http.StatusOK, gin.H{
			"code": -1,           // 错误码：-1表示参数错误
			"msg":  "用户名或密码不能为空", // 错误提示信息
		})
		return // 直接返回，不再执行后续逻辑
	}

	// 业务处理：根据账号和MD5加密后的密码查询用户信息
	ub, err := models.GetUserBasicByAccountPassword(account, helper.GetMd5(password))
	// 错误处理：如果查询出错（用户不存在或密码错误）
	if err != nil {
		c.JSON(http.StatusOK, gin.H{
			"code": -1,         // 返回错误状态码
			"msg":  "用户名或密码错误", // 返回错误提示信息
		})
		return // 终止函数执行，不再继续后续逻辑
	}

	// 生成JWT令牌，包含用户ID和邮箱信息
	token, err := helper.GenerateToken(ub.Identity, ub.Email)
	// 错误处理：如果令牌生成失败
	if err != nil {
		c.JSON(http.StatusOK, gin.H{"code": -1, "msg": "系统错误:" + err.Error()})
		return // 终止函数执行
	}

	// 返回登录成功响应
	c.JSON(http.StatusOK, gin.H{
		"code": 200,    // 状态码：200表示成功
		"msg":  "登录成功", // 消息：登录成功提示
		"data": gin.H{
			"token": token, // 数据：返回的JWT令牌
		},
	})
}

// UserDetail 获取用户详情接口处理函数
func UserDetail(c *gin.Context) {
	u, _ := c.Get("user_claims") // 从上下文中获取用户声明信息
	uc := u.(*helper.UserClaims) // 类型断言转换为UserClaims结构体

	// 根据用户ID查询用户基本信息
	userBasic, err := models.GetUserBasicByIdentity(uc.Identity)
	if err != nil {
		// 数据库查询错误，记录日志
		log.Printf("[DB ERROR]:%v\n", err)
		// 返回错误信息
		c.JSON(http.StatusOK, gin.H{
			"code": -1,
			"msg":  "数据查询异常",
		})
		return
	}

	// 查询成功，返回用户数据
	c.JSON(http.StatusOK, gin.H{
		"code": 200,
		"msg":  "数据加载成功",
		"data": userBasic,
	})
}

// UserQueryResult 用户信息查询结果结构体
type UserQueryResult struct {
	Nickname string `json:"nickname"`             // 用户昵称，JSON序列化字段名
	Sex      int    `bson:"sex" json:"sex"`       // 性别（0-未知 1-男 2-女），MongoDB字段名
	Email    string `bson:"email" json:"email"`   // 邮箱地址，MongoDB字段名
	Avatar   string `bson:"avatar" json:"avatar"` // 头像URL或路径，MongoDB字段名
	IsFriend bool   `json:"is_friend"`            // 是否是好友关系：true-是好友，false-非好友
}

// UserQuery 用户信息查询接口处理函数
func UserQuery(c *gin.Context) {
	account := c.Query("account") // 从URL查询参数中获取账号

	// 验证账号参数是否为空
	if account == "" {
		c.JSON(http.StatusOK, gin.H{"code": -1, "msg": "参数不正确"})
		return // 终止执行
	}

	// 根据账号查询用户基础信息
	userBasic, err := models.GetUserBasicByAccount(account)
	if err != nil {
		// 记录数据库查询错误日志
		log.Printf("[DB ERROR]:%v \n", err)
		c.JSON(http.StatusOK, gin.H{"code": -1, "msg": "数据查询异常"})
		return // 终止执行
	}

	// 从请求上下文中获取当前登录用户的身份信息
	uc := c.MustGet("user_claims").(*helper.UserClaims)

	// 初始化用户查询结果结构体
	data := UserQueryResult{
		Nickname: userBasic.Nickname, // 设置昵称（从数据库查询结果）
		Sex:      userBasic.Sex,      // 设置性别（从数据库查询结果）
		Email:    userBasic.Email,    // 设置邮箱（从数据库查询结果）
		Avatar:   userBasic.Avatar,   // 设置头像（从数据库查询结果）
		IsFriend: false,              // 默认设为非好友关系
	}

	// 判断并更新好友关系状态 判断目标用户与当前用户是否为好友关系
	if models.JudgeUserIsFriend(userBasic.Identity, uc.Identity) {
		data.IsFriend = true // 如果是好友，更新为true
	}

	// 返回成功的JSON响应
	c.JSON(http.StatusOK, gin.H{
		"code": 200,      // 状态码：200表示成功
		"msg":  "数据加载成功", // 成功提示消息
		"data": data,     // 包含用户信息的响应数据
	})
}

// SendCode 发送验证码
func SendCode(c *gin.Context) {
	email := c.PostForm("email") // 从POST表单获取邮箱地址

	// 检查邮箱是否为空
	if email == "" {
		c.JSON(http.StatusOK, gin.H{"code": -1, "msg": "邮箱不能为空"})
		return
	}

	// 根据邮箱查询用户数量，检查邮箱是否已被注册
	cnt, err := models.GetUserBasicCountByEmail(email)
	if err != nil {
		// 数据库查询错误，记录日志
		log.Printf("[DB ERROR]:%v\n", err)
		return
	}

	// 如果用户数量大于0，说明邮箱已被注册
	if cnt > 0 {
		c.JSON(http.StatusOK, gin.H{"code": -1, "msg": "当前邮箱已被注册"})
		return
	}

	// 邮箱未被注册，发送验证码
	code := helper.GetRand()

	println("验证码：", code)

	// 调用helper发送验证码邮件
	err = helper.SendCode(email, code)
	if err != nil {
		c.JSON(http.StatusOK, gin.H{
			"code": -1,
			"msg":  "Send Code Error:" + err.Error(),
		})
		return
	}

	// redis 保存数据
	if err := models.RDB.Set(
		context.Background(),        // 创建背景上下文
		define.RegisterPrefix+email, // 生成Redis键：TOKEN_邮箱地址
		code,                        // 存储的值：验证码
		time.Second*time.Duration(define.ExpireTime), // 过期时间：300秒（5分钟）
	).Err(); err != nil {
		log.Printf("[ERROR]:#{err} \n") // 记录错误日志到控制台，包含错误详情
		c.JSON(http.StatusOK, gin.H{"code": -1, "msg": "系统错误"})
		return
	}

	//models.RDB.Set(
	//	context.Background(), // 创建背景上下文
	//	"TOKEN_"+email,       // 生成Redis键：TOKEN_邮箱地址
	//	code,                 // 存储的值：验证码
	//	time.Second*300,      // 过期时间：300秒（5分钟）
	//)

	c.JSON(http.StatusOK, gin.H{
		"code": 200,
		"msg":  "验证码发送成功",
	})
}

// Register 用户注册
func Register(c *gin.Context) {
	// 获取用户提交的注册参数
	code := c.PostForm("code")         // 验证码
	email := c.PostForm("email")       // 邮箱
	account := c.PostForm("account")   // 账号
	password := c.PostForm("password") // 密码

	// 检查必填参数是否为空
	if code == "" || email == "" || account == "" || password == "" {
		c.JSON(http.StatusOK, gin.H{"code": -1, "msg": "参数不正确"})
		return // 终止执行
	}

	// 从Redis获取该邮箱对应的验证码
	r, err := models.RDB.Get(context.Background(), define.RegisterPrefix+email).Result()
	if err != nil {
		c.JSON(http.StatusOK, gin.H{"code": -1, "msg": "验证码不正确"})
		return
	}

	// 判断账号是否唯一
	cnt, err := models.GetUserBasicCountByAccount(account) // 查询数据库中该账号的用户数量
	if err != nil {
		log.Printf("[DB ERROR]:%v \n", err) // 记录数据库错误日志
		c.JSON(http.StatusOK, gin.H{"code": -1, "msg": "系统错误"})
		return // 终止函数执行
	}
	if cnt > 0 {
		// 账号已存在，返回重复注册提示
		c.JSON(http.StatusOK, gin.H{"code": -1, "msg": "账号已被注册"})
		return // 终止函数执行
	}

	// 比较用户输入的验证码与Redis中存储的是否一致
	if r != code { // 验证码不匹配
		c.JSON(http.StatusOK, gin.H{"code": -1, "msg": "验证码不正确"})
		return
	}

	// 初始化用户基础信息结构体
	ub := &models.UserBasic{
		Identity:  helper.GetUUID(),        // 生成唯一用户标识（UUID）
		Account:   account,                 // 用户账号（从请求参数获取）
		Password:  helper.GetMd5(password), // 密码经过MD5加密处理
		Email:     email,                   // 用户邮箱
		CreatedAt: time.Now().Unix(),       // 记录创建时间（当前时间戳）
		UpdatedAt: time.Now().Unix(),       // 记录更新时间（当前时间戳）
	}

	// 将用户信息插入数据库
	if err = models.InsertOneUserBasic(ub); err != nil {
		log.Printf("[DB ERROR]:%v \n", err) // 记录详细错误日志
		c.JSON(http.StatusOK, gin.H{"code": -1, "msg": "系统错误"})
		return // 终止注册流程
	}

	// 生成JWT令牌，包含用户ID和邮箱信息
	token, err := helper.GenerateToken(ub.Identity, ub.Email)
	// 错误处理：如果令牌生成失败
	if err != nil {
		c.JSON(http.StatusOK, gin.H{"code": -1, "msg": "系统错误:" + err.Error()})
		return // 终止函数执行
	}

	// 返回登录成功响应
	c.JSON(http.StatusOK, gin.H{
		"code": 200,    // 状态码：200表示成功
		"msg":  "注册成功", // 消息：登录成功提示
		"data": gin.H{
			"token": token, // 数据：返回的JWT令牌
		},
	})
}

// UserAdd 用户添加接口处理函数
func UserAdd(c *gin.Context) {
	// 从POST表单中获取账号参数
	account := c.PostForm("account")

	// 验证账号参数是否为空
	if account == "" {
		c.JSON(http.StatusOK, gin.H{"code": -1, "msg": "参数不正确"})
		return
	}

	// 根据账号查询用户基本信息
	ub, err := models.GetUserBasicByAccount(account)
	if err != nil {
		log.Printf("[DB ERROR]:%v\n", err) // 打印数据库错误日志
		c.JSON(http.StatusOK, gin.H{"code": -1, "msg": "数据查询异常"})
		return // 终止执行
	}

	// 获取当前登录用户的身份信息
	uc := c.MustGet("user_claims").(*helper.UserClaims)
	// 判断是否为好友关系，如果是则更新标记
	if models.JudgeUserIsFriend(ub.Identity, uc.Identity) {
		c.JSON(http.StatusOK, gin.H{"code": -1, "msg": "互为好友，不可重复添加"})
		return // 终止执行
	}

	// 保存房间记录
	rb := &models.RoomBasic{
		Identity:     helper.GetUUID(),  // 生成房间唯一标识（UUID）
		UserIdentity: uc.Identity,       // 设置房间创建者的用户标识
		CreatedAt:    time.Now().Unix(), // 记录创建时间（当前时间戳）
		UpdatedAt:    time.Now().Unix(), // 记录更新时间（当前时间戳）
	}
	// 调用数据层方法，将房间信息插入数据库
	if err = models.InsertOneRoomBasic(rb); err != nil {
		log.Printf("[DB ERROR]:%v\n", err) // 打印数据库错误日志
		c.JSON(http.StatusOK, gin.H{"code": -1, "msg": "数据添加失败"})
		return
	}

	// 保存用户与房间的关联记录
	ur := &models.UserRoom{
		UserIdentity: uc.Identity,       // 当前用户唯一标识
		RoomIdentity: rb.Identity,       // 房间唯一标识
		RoomType:     1,                 // 房间类型：1-单聊房间
		CreatedAt:    time.Now().Unix(), // 记录创建时间戳
		UpdatedAt:    time.Now().Unix(), // 记录更新时间戳
	}
	// 将关联记录插入数据库
	if err := models.InsertOneUserRoom(ur); err != nil {
		log.Printf("[DB ERROR]:%v\n", err) // 打印数据库错误日志
		c.JSON(http.StatusOK, gin.H{"code": -1, "msg": "数据添加失败"})
		return
	}

	// --- 另一个 用户 也插入数据库 ---------

	// 用户-房间关联记录对象
	ur = &models.UserRoom{
		UserIdentity: ub.Identity,       // 目标用户的唯一标识
		RoomIdentity: rb.Identity,       // 房间的唯一标识
		RoomType:     1,                 // 房间类型：1-单聊房间
		CreatedAt:    time.Now().Unix(), // 记录创建时间戳
		UpdatedAt:    time.Now().Unix(), // 记录更新时间戳
	}

	// 将关联记录插入数据库
	if err = models.InsertOneUserRoom(ur); err != nil {
		// 插入失败处理：记录错误日志并返回异常响应
		log.Printf("DB ERROR:%v\n", err) // 打印数据库错误详情
		c.JSON(http.StatusOK, gin.H{
			"code": -1,      // 错误状态码
			"msg":  "数据库异常", // 错误提示信息
		})
		return // 终止执行
	}

	// 插入成功：返回操作成功响应
	c.JSON(http.StatusOK, gin.H{
		"code": 200,    // 成功状态码
		"msg":  "添加成功", // 成功提示信息
	})

}

// UserDelete 删除好友
func UserDelete(c *gin.Context) {
	// 从URL查询参数中获取要删除的好友身份标识
	identity := c.Query("identity")

	// 验证身份标识参数是否为空
	if identity == "" {
		c.JSON(http.StatusOK, gin.H{"code": -1, "msg": "参数不正确"})
		return // 终止函数执行
	}

	// 获取房间Identity
	// 从请求上下文中获取当前登录用户的身份信息
	uc := c.MustGet("user_claims").(*helper.UserClaims)

	// 获取两个用户之间的房间标识（判断是否为好友关系）
	roomIdentity := models.GetUserRoomIdentity(identity, uc.Identity)

	// 检查房间标识是否为空（空表示不是好友关系）
	if roomIdentity == "" {
		c.JSON(http.StatusOK, gin.H{"code": -1, "msg": "不为好友关系，无需删除"})
		return // 终止函数执行
	}

	// 删除user_room关联关系
	if err := models.DeleteUserRoom(roomIdentity); err != nil {
		c.JSON(http.StatusOK, gin.H{"code": -1, "msg": "系统异常"})
		return // 终止执行
	}

	// 删除room_basic（房间基础信息）
	// 删除房间基础信息记录
	if err := models.DeleteRoomBasic(roomIdentity); err != nil {
		// 删除失败：返回系统异常错误响应
		c.JSON(http.StatusOK, gin.H{
			"code": -1,     // 错误状态码
			"msg":  "系统异常", // 错误提示信息
		})
		return // 终止执行
	}

	// 删除成功：返回操作成功响应
	c.JSON(http.StatusOK, gin.H{
		"code": 200,    // 成功状态码
		"msg":  "删除成功", // 成功提示信息
	})
}
